package MathTextModeller
{
	import MathText.WordProblem;
	
	import MyDisplayObjects.MyButton;
	import MyDisplayObjects.PopUpTextField;
	import MyDisplayObjects.TextFeedbackDisplay;
	import TaskStructure.LogEvent;
	import flash.display.MovieClip;
	import flash.display.Shape;
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	/** An object of this class primarily displays the sentenceDisplayPanel, which is used to model the action.  Also display buttons to go forward and back. */
	public class ActionModeller extends MovieClip
	{	
		// public vars
		public var currentSentenceDisplay:SentenceDisplay;
		public var numberModel:NumberModel;
		
		// private vars
		private var wordProblem:WordProblem;
		private var errorsXML:XML;
		private var textFeedbackDisplay:TextFeedbackDisplay;
		private var continueButton:MyButton;
		private var editButton:MyButton;
		private var sentenceDisplays:Array;
		private var panel:SentenceDisplayPanel;
		private var sentenceHighlighter:Shape;
		private var rewardText:PopUpTextField
		
		public function ActionModeller(sentenceDisplays:Array, wordProblem:WordProblem, errorsXML:XML)
		{
			this.sentenceDisplays = sentenceDisplays;
			this.wordProblem = wordProblem;
			this.errorsXML = errorsXML;
			this.addEventListener(Event.ADDED, handleAdded);
		}
		private function handleAdded(event:Event):void
		{
			this.removeEventListener(Event.ADDED, handleAdded);
			this.graphics.drawRect(0, 0, parent.width, parent.height);
			panel = new SentenceDisplayPanel (sentenceDisplays, this.width, this.height);
			panel.y = (this.height - panel.height)/2;
			this.addChild(panel);
			
			numberModel = new NumberModel (this.width, panel.y);
			numberModel.x = (this.width - numberModel.width)/2;
			this.addChild(numberModel);
			
			textFeedbackDisplay = new TextFeedbackDisplay(this.width*3/4, (this.height-panel.height)/2, panel.width/40, panel.width/40, panel.width/50, 0x444444, 0xEEEEEE, "Can you fill the unknown box with objects?"); 
			textFeedbackDisplay.x = 0;
			textFeedbackDisplay.y = panel.y + panel.height;
			this.addChild(textFeedbackDisplay);				
			
			// place a button that allow user to edit sentences
			editButton = new MyButton(this.width-textFeedbackDisplay.width-textFeedbackDisplay.height/10, (textFeedbackDisplay.height-textFeedbackDisplay.height/10)/2, textFeedbackDisplay.height/10, textFeedbackDisplay.height/10, "Change a sentence.", 0x880000, 1);
			editButton.addEventListener(MouseEvent.CLICK, handleEditPressed);
			this.addChild(editButton);
			editButton.x = textFeedbackDisplay.x + textFeedbackDisplay.width;
			editButton.y = textFeedbackDisplay.y;
			
			// place a continue button, place a listener so when completed this completes as well.
			continueButton = new MyButton(this.width-textFeedbackDisplay.width-textFeedbackDisplay.height/10, (textFeedbackDisplay.height-textFeedbackDisplay.height/10)/2, textFeedbackDisplay.height/10, textFeedbackDisplay.height/10, "I'm finished.", 0x008800, 1);
			continueButton.addEventListener(MouseEvent.CLICK, handleContinuePressed);
			this.addChild(continueButton);
			continueButton.x = textFeedbackDisplay.x + textFeedbackDisplay.width;
			continueButton.y = editButton.y + editButton.height;
			
			checkInitialConditions();
		}
		
		///////////////////////////////////// MENU STUFF /////////////////////////////////////////////////////////////////////////////
		/** When user clicks the edit button the user can click on a sentence display to edit, which will eventually result in a dispatch cancel event */
		private function handleEditPressed (event:MouseEvent):void
		{
			editButton.removeEventListener(MouseEvent.CLICK, handleEditPressed);
			event.stopImmediatePropagation();
			continueButton.removeEventListener(MouseEvent.CLICK, handleContinuePressed);
			textFeedbackDisplay.newFeedback("Click on a sentence box you would like to change.  Click button again to keep going.");
			panel.returnAllToOrigins();
			sentenceHighlighter = new Shape();
			panel.addChild(sentenceHighlighter);
			for each (var sentenceDisplay:SentenceDisplay in sentenceDisplays)
			{
				sentenceDisplay.addEventListener(MouseEvent.MOUSE_OVER, handleMouseOverSentenceDisplay);
			}
			continueButton.addEventListener(MouseEvent.CLICK, handleEditComplete);
		}
		private function handleMouseOverSentenceDisplay (event:MouseEvent):void
		{
			event.currentTarget.removeEventListener(MouseEvent.MOUSE_OVER, handleMouseOverSentenceDisplay);
			sentenceHighlighter.graphics.lineStyle(panel.width/100, 0xFFFF00);
			sentenceHighlighter.graphics.drawRect(0, 0, event.currentTarget.width, event.currentTarget.height);
			sentenceHighlighter.x = event.currentTarget.x;
			sentenceHighlighter.y = event.currentTarget.y;
			event.currentTarget.addEventListener(MouseEvent.MOUSE_OUT, handleMouseOutSentenceDisplay);
			event.currentTarget.addEventListener(MouseEvent.CLICK, handleClickSentenceDisplay);
		}
		private function handleMouseOutSentenceDisplay (event:MouseEvent):void
		{
			event.currentTarget.removeEventListener(MouseEvent.MOUSE_OUT, handleMouseOutSentenceDisplay);
			event.currentTarget.removeEventListener(MouseEvent.CLICK, handleClickSentenceDisplay);
			sentenceHighlighter.graphics.clear();
			event.currentTarget.addEventListener(MouseEvent.MOUSE_OVER, handleMouseOverSentenceDisplay);				
		}
		private function handleClickSentenceDisplay (event:MouseEvent):void
		{
			event.currentTarget.removeEventListener(MouseEvent.MOUSE_OUT, handleMouseOutSentenceDisplay);
			event.currentTarget.removeEventListener(MouseEvent.CLICK, handleClickSentenceDisplay);
			//editButton.removeEventListener(MouseEvent.CLICK, handleEditComplete);
			continueButton.removeEventListener(MouseEvent.CLICK, handleEditComplete);
			currentSentenceDisplay = SentenceDisplay(event.currentTarget); 
			for each (var s:SentenceDisplay in sentenceDisplays)
			{
				s.transitionFromPanelView();
				s.removeEventListener(MouseEvent.MOUSE_OVER, handleMouseOverSentenceDisplay);
			}
			panel.removeAll();
			if (sentenceHighlighter.parent == panel) panel.removeChild(sentenceHighlighter);				
			this.dispatchEvent(new LogEvent(LogEvent.TRANSITION, "back", currentSentenceDisplay.name, currentSentenceDisplay.x, currentSentenceDisplay.y));
			this.dispatchEvent( new Event(Event.CANCEL));					
		}
		private function handleEditComplete (event:MouseEvent):void
		{
			//editButton.removeEventListener(MouseEvent.CLICK, handleEditComplete);
			continueButton.removeEventListener(MouseEvent.CLICK, handleEditComplete);
			if (sentenceHighlighter != null && sentenceHighlighter.parent == this) this.removeChild(sentenceHighlighter);	
			for each (var sentenceDisplay:SentenceDisplay in sentenceDisplays)
			{
				sentenceDisplay.removeEventListener(MouseEvent.MOUSE_OVER, handleMouseOverSentenceDisplay);
			}
			continueButton.addEventListener(MouseEvent.CLICK, handleContinuePressed);
			editButton.addEventListener(MouseEvent.CLICK, handleEditPressed);
			
		}
		
		/** When user clicks the continue button dispatch complete event */
		private function handleContinuePressed (event:Event):void
		{
			continueButton.removeEventListener(MouseEvent.CLICK, handleContinuePressed);
			if (checkFinalConditions())
			{
				this.dispatchEvent(new LogEvent(LogEvent.TRANSITION, "completed", "", continueButton.x, continueButton.y));
				complete();
			} else
			{
				continueButton.addEventListener(MouseEvent.CLICK, handleContinuePressed);
			}
		}
		
		/** Have we met initial conditions */
		private function checkInitialConditions ():Boolean
		{
			var node:XML;
		
			if (errorsXML..actionModel..error.(attribute("id")=="MULTIPLE_VARIABLES").length() > 0)
			{
				node = errorsXML..actionModel..error.(attribute("id")=="MULTIPLE_VARIABLES")[0];
				// make sure it is enabled
				if (node.attribute("enabled") != "false" && node.attribute("checkAtInitial") == "true")
				{
					if (panel.numVariables > 1)
					{
						textFeedbackDisplay.newFeedback(node.toString());
						return false;
					}
				}
			}
			return true;
		}
		/** Have we met final conditions (mainly, is the number model correct and does it match the problem) */
		private function checkFinalConditions ():Boolean
		{
			var node:XML;
			if (errorsXML..actionModel..error.(attribute("id")=="NO_EQUAL_SIGN_NUMBERMODEL").length() > 0)
			{
				node = errorsXML..actionModel..error.(attribute("id")=="NO_EQUAL_SIGN_NUMBERMODEL")[0];
				// make sure it is enabled
				if (node.attribute("enabled") != "false" && node.attribute("halting") != "false" && node.attribute("checkAtFinal") != "false")
				{
					if (numberModel.leftOperationName != "=" && numberModel.rightOperationName != "=")
					{
						textFeedbackDisplay.newFeedback(node.toString());
						return false;
					}
				}
			}
			if (errorsXML..actionModel..error.(attribute("id")=="NO_OPERATION_NUMBERMODEL").length() > 0)
			{
				node = errorsXML..actionModel..error.(attribute("id")=="NO_OPERATION_NUMBERMODEL")[0];
				// make sure it is enabled
				if (node.attribute("enabled") != "false" && node.attribute("halting") != "false" && node.attribute("checkAtFinal") != "false")
				{
					if (numberModel.leftOperationName != "+" && numberModel.leftOperationName != "-" && numberModel.rightOperationName != "+" && numberModel.rightOperationName != "-")
					{
						textFeedbackDisplay.newFeedback(node.toString());
						return false;
					}
				}
			} 
			if (errorsXML..actionModel..error.(attribute("id")=="NONMATCHING_OPERATION_NUMBERMODEL").length() > 0)
			{
				node = errorsXML..actionModel..error.(attribute("id")=="NONMATCHING_OPERATION_NUMBERMODEL")[0];
				// make sure it is enabled
				if (node.attribute("enabled") != "false" && node.attribute("halting") != "false" && node.attribute("checkAtFinal") != "false")
				{
					if (wordProblem.operation != numberModel.leftOperationName && wordProblem.operation != numberModel.rightOperationName)
					{
						textFeedbackDisplay.newFeedback(node.toString());
						return false;
					}
				}
			} 
			if (errorsXML..actionModel..error.(attribute("id")=="INCORRECT_NUMBERMODEL").length() > 0)
			{
				node = errorsXML..actionModel..error.(attribute("id")=="INCORRECT_NUMBERMODEL")[0];
				// make sure it is enabled
				if (node.attribute("enabled") != "false" && node.attribute("halting") != "false" && node.attribute("checkAtFinal") != "false")
				{
					if (numberModel.leftOperationName == "=")
					{
						if (numberModel.rightOperationName == "+")
						{
							if (numberModel.leftValue != numberModel.middleValue + numberModel.rightValue)
							{
								textFeedbackDisplay.newFeedback(node.toString());
								return false;
							}
						} else if (numberModel.rightOperationName == "-")
						{
							if (numberModel.leftValue != numberModel.middleValue - numberModel.rightValue)
							{
								textFeedbackDisplay.newFeedback(node.toString());
								return false;
							}
						} else { return false; }
					} else if (numberModel.rightOperationName == "=")
					{
						if (numberModel.leftOperationName == "+")	
						{
							if (numberModel.rightValue != numberModel.leftValue + numberModel.middleValue)
							{
								textFeedbackDisplay.newFeedback(node.toString());
								return false;
							}
						} else if (numberModel.leftOperationName == "-")
						{
							if (numberModel.rightValue != numberModel.leftValue - numberModel.middleValue)
							{
								textFeedbackDisplay.newFeedback(node.toString());
								return false;
							}
						} else { return false; }
					}
				} 
			}
			if (errorsXML..actionModel..error.(attribute("id")=="NONMATCHING_NUMBER_NUMBERMODEL").length() > 0)
			{
				node = errorsXML..actionModel..error.(attribute("id")=="NONMATCHING_NUMBER_NUMBERMODEL")[0];
				// make sure it is enabled
				if (node.attribute("enabled") != "false" && node.attribute("halting") != "false" && node.attribute("checkAtFinal") != "false")
				{
					var leftIn:Boolean = (numberModel.leftValue == wordProblem.addend1) || (numberModel.leftValue == wordProblem.addend2) || (numberModel.leftValue == wordProblem.total)
					var middleIn:Boolean = (numberModel.middleValue == wordProblem.addend1) || (numberModel.middleValue == wordProblem.addend2) || (numberModel.middleValue == wordProblem.total)
					var rightIn:Boolean = (numberModel.rightValue == wordProblem.addend1) || (numberModel.rightValue == wordProblem.addend2) || (numberModel.rightValue == wordProblem.total)
							
					if (!leftIn || !middleIn || !rightIn)
					{
						textFeedbackDisplay.newFeedback(node.toString());
						return false;
					}
				}
			} 
			return true;
		}
		
		/** Called when user has met all conditions */
		private function complete():void
		{
			rewardText = new PopUpTextField("Great Job!", panel.height/4, 0xFF0000, 2000, 0x00FF00);
			rewardText.addEventListener(Event.COMPLETE, _complete);
			rewardText.x = (this.width - rewardText.width)/2;
			rewardText.y = (this.height - rewardText.height)/2;
			this.addChild(rewardText);
		}
			private function _complete(event:Event):void
			{
				rewardText.removeEventListener(Event.COMPLETE, _complete);
				this.removeChild(rewardText);
				editButton.removeEventListener(MouseEvent.CLICK, handleEditPressed);
				continueButton.removeEventListener(MouseEvent.CLICK, handleContinuePressed);
				panel.removeAll();
				this.dispatchEvent (new Event(Event.COMPLETE));
			}
	
	}
}